﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace SkyBase
{
    class Weapon : Item
    {
        public int BaseDamage { get; set; }
        public int Speed { get; set; }
        public int AttuneLevel { get; set; }
        public int AttuneExp { get; set; }
        public int EnergyMax { get; set; }
        public int EnergyCurr { get; set; }

        private Texture2D Projectile { get; set; } //optional, use for projectile weapons. Sprite of projectile.
        public Texture2D EquipSprite { get; set; }

        //Bonus stats on weapons; NYI.
        //Bonus stats are only applied when a weapon has power.
        public int BonusHealth { get; set; }
        public int BonusRunSpeed { get; set; }
        public int BonusDamage { get; set; }
        public int DamageReduction { get; set; }

        public Weapon(string item_name, string item_desc, string item_type, int item_range, Texture2D spriteIn, Texture2D equipSprite, World worldIn, int baseDamage, int speed, int energyMax, int energyCurr)
            : base(item_name, item_desc, item_type, item_range, spriteIn, worldIn)
        {
            BaseDamage = baseDamage;
            Speed = speed;
            EnergyMax = energyMax;
            EnergyCurr = energyCurr;
            AttuneLevel = 1;
            AttuneExp = 0;
            checkForCollision = true;
            ghost = true;
            EquipSprite = equipSprite;
        }

        //For use of weapons with projectiles
        public Weapon(string item_name, string item_desc, string item_type, int item_range, Texture2D spriteIn, Texture2D equipSprite, World worldIn, int baseDamage, int speed, int energyMax, int energyCurr, Texture2D projectile)
            : base(item_name, item_desc, item_type, item_range, spriteIn, worldIn)
        {
            BaseDamage = baseDamage;
            Speed = speed;
            EnergyMax = energyMax;
            EnergyCurr = energyCurr;
            AttuneLevel = 1;
            AttuneExp = 0;
            Projectile = projectile;
            EquipSprite = equipSprite;
        }

        public void Use(GameObject[] targets, Player player)
        {
            //double direction = player.Rotation();
            if (EnergyCurr > 0)
            {
                //apply magicy/glowy visual effect to weapon
                EnergyCurr -= 1;
            }

            //reminder for me: DO NOT include player in these collision detections
            if (this.Type.Equals("melee"))
            {
                //tell world to animate in direction
                //in world, check collision
                //if collision, deal damage, +1 attuneExp
            }
            else if (this.Type.Equals("ranged"))
            {
                //tell world to animate in direction
                //place in World a new item using the Projectile sprite
                //move projectile_object until it hits another GameObject or moves [range] units
                //deal damage if collision, +1 attuneExp
                //remove projectile_object
            }
        }

        //USE THIS, not constructor class to gen RANDOM weapons that appear on the floor!
        public static Weapon GenRandomWeapon(int floor, Random r, World world)
        {
            Weapon newWeapon = new Weapon("tempName", "Temp item for genning", "", 0, null, null, world, 0, 0, 0, 0);

            int type = r.Next(0, 2);
            if (type == 0)
            {
                newWeapon.Type = "melee";
                newWeapon.Desc = "A sword";
                newWeapon.Range = r.Next(1, 3);
                newWeapon.Sprite = Storage.getTexture("Sword");
                newWeapon.EquipSprite = Storage.getTexture("SwordEquip");
            }
            else
            {
                newWeapon.Type = "ranged";
                newWeapon.Desc = "A gun";
                newWeapon.Range = r.Next(5, 11);
                newWeapon.Sprite = Storage.getTexture("Gun");
                newWeapon.EquipSprite = Storage.getTexture("GunEquip");
                newWeapon.Projectile = Storage.getTexture("bullet");
            }
            double dbl = r.NextDouble();
            int numBonus = 0;
            if (dbl <= 0.05)
                numBonus = 4;
            else if (dbl > 0.05 && dbl <= 0.15)
                numBonus = 3;
            else if (dbl > 0.15 && dbl <= 0.35)
                numBonus = 2;
            else if (dbl > 0.35 && dbl <= 0.67)
                numBonus = 1;

            newWeapon.BonusDamage = 0;
            newWeapon.BonusHealth = 0;
            newWeapon.BonusRunSpeed = 0;
            newWeapon.DamageReduction = 0;

            newWeapon = SetRandomVals(numBonus, floor, r, newWeapon);
            newWeapon = SetRandName(newWeapon);
            return newWeapon;
        }

        public static Weapon SetRandomVals(int numBonus, int floor, Random r, Weapon newWeapon)
        {
            int n = 0;
            int stat = 0;
            while (n < numBonus)
            {
                stat = r.Next(0, 4);
                if (stat == 0 && newWeapon.BonusHealth == 0)
                {
                    newWeapon.BonusHealth = r.Next(floor, floor * 2);
                    n += 1;
                }
                else if (stat == 1 && newWeapon.BonusRunSpeed == 0)
                {
                    newWeapon.BonusRunSpeed = r.Next(floor, floor * 2);
                    n += 1;
                }
                else if (stat == 2 && newWeapon.BonusDamage == 0)
                {
                    newWeapon.BonusDamage = r.Next(floor, floor * 2);
                    n += 1;
                }
                else if (stat == 3 && newWeapon.DamageReduction == 0)
                {
                    newWeapon.DamageReduction = r.Next(floor, floor * 2);
                    n += 1;
                }
            }
            newWeapon.Speed = r.Next(1, 5);
            newWeapon.BaseDamage = r.Next((floor * 3), (floor * 5));
            newWeapon.EnergyMax = 100 + (r.Next(floor, (floor * 15)));
            double d = r.NextDouble();
            if (d < (0.10 + (double)floor / 10))
                newWeapon.EnergyCurr = r.Next(0, newWeapon.EnergyMax + 1);
            else
                newWeapon.EnergyCurr = 0;

            return newWeapon;
        }

        public static Weapon SetRandName(Weapon newWeapon)
        {
            if (newWeapon.Type.Equals("melee"))
                newWeapon.Name = "Sword";
            else if (newWeapon.Type.Equals("ranged"))
                newWeapon.Name = "Gun";

            //sets unique number for stat combo
            int value = 0;
            if (newWeapon.BonusHealth != 0)
                value += 1;
            if (newWeapon.BonusDamage != 0)
                value += 3;
            if (newWeapon.BonusRunSpeed != 0)
                value += 7;
            if (newWeapon.DamageReduction != 0)
                value += 13;
            //Based on unique number, assign name
            if (value == 1)
                newWeapon.Name = newWeapon.Name + " of Stamina";
            else if (value == 3)
                newWeapon.Name = newWeapon.Name + " of Striking";
            else if (value == 7)
                newWeapon.Name = newWeapon.Name + " of Sprinting";
            else if (value == 13)
                newWeapon.Name = newWeapon.Name + " of Warding";
            else if (value == 4)
                newWeapon.Name = "Fierce " + newWeapon.Name + " of Stamina";
            else if (value == 8)
                newWeapon.Name = "Swift " + newWeapon.Name + " of Stamina";
            else if (value == 14)
                newWeapon.Name = "Vigorous " + newWeapon.Name + " of Warding";
            else if (value == 10)
                newWeapon.Name = "Swift " + newWeapon.Name + " of Striking";
            else if (value == 16)
                newWeapon.Name = "Fierce " + newWeapon.Name + " of Warding";
            else if (value == 20)
                newWeapon.Name = "Swift " + newWeapon.Name + " of Warding";
            else if (value == 11)
                newWeapon.Name = "Swift " + newWeapon.Name + " of the Knight";
            else if (value == 21)
                newWeapon.Name = "Vigorous " + newWeapon.Name + " of the Nimble";
            else if (value == 23)
                newWeapon.Name = "Fierce " + newWeapon.Name + " of the Nimble";
            else if (value == 24)
                newWeapon.Name = newWeapon.Name + " of Wonder";

            return newWeapon;
        }

        public string GetBonus()
        {
            string s = "";
            if (BonusHealth > 0)
                s += "+" + BonusHealth + " Bonus Health" + '\n';
            if (BonusDamage > 0)
                s += "+" + BonusDamage + " Bonus Damage" + '\n';
            if (BonusRunSpeed > 0)
                s += "+" + BonusRunSpeed + " Run Speed" + '\n';
            if (DamageReduction > 0)
                s += "-" + DamageReduction + " Damage Taken";
            return s;
        }

        public override string ToString()
        {
            string s = (Name + " (" + Type + ") - " + BaseDamage + " Damage, " + Speed + "WS, " + EnergyCurr + "/" + EnergyMax + " EN");
            if (BonusHealth != 0) s += (" BH: " + BonusHealth);
            if (BonusDamage != 0) s += (" BD: " + BonusDamage);
            if (BonusRunSpeed != 0) s += (" RS: " + BonusRunSpeed);
            if (DamageReduction != 0) s += (" DR: " + DamageReduction);
            return s;
        }

        public override void onCollision(GameObject collidee)
        {
            //TODO: Fill this out so we can pickup weapons!
            //MAKE SURE TO REMOVE THE WEAPON AFTER THIS METHOD IS OVER!

            Debugger.enabled = true;
            if (parent == null && collidee is Player && !(collidee is Enemy))
            {
                Item[] inventory = (collidee as Player).Inventory;
                if (inventory[inventory.Length - 1] == null)
                {
                    for (int i = 0; i < inventory.Length; i++)
                    {
                        if (inventory[i] == null)
                        {
                            inventory[i] = this;
                            break;
                        }

                    }
                    Debugger.writeLine("REMOVING");
                    parent = collidee;
                    if (duplicateNum > 0)
                        world.toRemove.Add(Name + duplicateNum.ToString("0000"));
                    else
                        world.toRemove.Add(Name);
                    Debugger.writeLine("Added " + Name + " to inventory: " + inventory.ToString());
                }

            }
        }
    }
}
